//---------------------------------------------------------------------------

#include "vcl_stl.h"
#pragma hdrstop

#include <algorithm>

#include "h_base.h"
#include "h_xml.h"
#include "h_global.h"
using namespace h_base;
using namespace h_xml;

#include "h_g.h"
#include "h_i18n.h"
#include "h_scrollingwincontrol.h"
#include "t_mainform.h"

#include "t_concurrencyform.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TConcurrencyForm *ConcurrencyForm;
//---------------------------------------------------------------------------
bool __fastcall operator<(const HPartTimeInfo &lhs, const HPartTimeInfo &rhs)
{
   return lhs.StartTime < rhs.StartTime;
}

__fastcall TConcurrencyForm::TConcurrencyForm(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TConcurrencyForm::Init()
{
   ShowPanelFlag = true;
   WindowHeightIdx = 0;
   ComboBoxPeriod->ItemIndex = 2;
   ScrollingWinControl1 = new HScrollingWinControl(this);

   ScrollingWinControl1->Left = 200;
   ScrollingWinControl1->Top = 200;
   ScrollingWinControl1->Align = alClient;
   ScrollingWinControl1->TabStop = true;
   ScrollingWinControl1->Parent = this;
   ScrollingWinControl1->DoubleBuffered = true;
   Image1 = new TImage(ScrollingWinControl1);
   Image1->Left = 0;
   Image1->Top = 0;
   Image1->Parent = ScrollingWinControl1;
   Image1->Width = 1900;
   Image1->Height = 900;
   DrawBackground();
}

void __fastcall TConcurrencyForm::ShowIt()
{
   MainForm->SaveToPartTimeList(PartVec);
   sort(PartVec.begin(), PartVec.end());

   BatchStartTimeStr = "";
   BatchEndTimeStr = "";

   for ( int i = 0; i < PartVec.size(); i++ )
   {
      HPartTimeInfo &Info = PartVec[i];
      if ( i == 0 )
      {
         BatchStartTimeStr = Info.StartTime;
      }
      if ( Info.EndTime > BatchEndTimeStr )
      {
         BatchEndTimeStr = Info.EndTime;
      }
   }

   EditEndTime->Text = FormatDateTime(BatchEndTimeStr);
   ShowModal();
}

struct HPeriodInfo
{
   int TotalSec;
   int BlockQty;
   bool HourFlag;
};

static int StartX = 96;
static int EndX = 1878;
static int LengthX = EndX - StartX;
static int StartY = 346;
static int EndY = 547;
static int LengthY = EndY - StartY;
static HPeriodInfo PeriodArray[] =
{
   { 24 * 3600, 48, true },
   { 12 * 3600, 48, true },
   { 6 * 3600, 72, true },
   { 3 * 3600, 90, true },
   { 2 * 3600, 60, true },
   { 3600, 60, true },
   { 30 * 60, 60, false },
   { 15 * 60, 90, false },
   { 5 * 60, 60, false }
};

void __fastcall TConcurrencyForm::DrawBackground()
{
   Image1->Canvas->Brush->Color = (TColor)RGB(43, 43, 43);
   Image1->Canvas->FillRect(Image1->ClientRect);

   Image1->Canvas->Pen->Color = (TColor)RGB(79, 79, 79);
   Image1->Canvas->Pen->Mode = pmCopy;
   Image1->Canvas->Pen->Style = psSolid;
   Image1->Canvas->MoveTo(LEFT + StartX - 4, TOP + EndY);
   Image1->Canvas->LineTo(LEFT + EndX + 4, TOP + EndY);
   Image1->Canvas->MoveTo(LEFT + StartX, TOP + StartY - 4);
   Image1->Canvas->LineTo(LEFT + StartX, TOP + EndY + 4);
   ImageList1->DrawingStyle = dsTransparent;
   ImageList1->Draw(Image1->Canvas, LEFT + 93, TOP + 336, 0, true);
   ImageList1->Draw(Image1->Canvas, LEFT + 1882, TOP + 543, 1, true);

   Image1->Canvas->Pen->Color = (TColor)RGB(69, 69, 69);
   Image1->Canvas->Pen->Style = psDot;

   for ( int i = 0; i < 12; i++ )
   {
      int y = StartY + (int)(LengthY / 12.0 * i + 0.5);
      Image1->Canvas->MoveTo(LEFT + StartX + 1, TOP + y);
      Image1->Canvas->LineTo(LEFT + EndX, TOP + y);
   }

   Image1->Canvas->MoveTo(LEFT + EndX, TOP + StartY);
   Image1->Canvas->LineTo(LEFT + EndX, TOP + EndY);
}

void __fastcall TConcurrencyForm::PrepareData()
{
   TDateTime BatchStartTime;
   TDateTime BatchEndTime;

   SplitterVec.clear();
   ParaTimeVec.clear();

   if ( !StringToDateTime(BatchStartTimeStr, BatchStartTime) ||
        !StringToDateTime(BatchEndTimeStr, BatchEndTime) )
   {
      return;
   }

   int TotalTime = SubDateTime(BatchEndTime, BatchStartTime);
   vector<int> ParaVec;

   for ( int i = 0; i <= TotalTime; i++ )
   {
      ParaVec.push_back(0);
   }

   int ParaVecSize = ParaVec.size();
   int VecSize = PartVec.size();
   set<string> SectionSet;

   {
      TMainForm::HInfo Info;
      MainForm->GetInfo(Info);
      vector<string> StrVec;
      SplitString(Info.SectionList.c_str(), ',', StrVec, true);
      for ( int i = 0; i < StrVec.size(); i++ )
      {
         SectionSet.insert(StrVec[i]);
      }
   }

   if ( !SectionSet.empty() )
   {
      MainForm->ReloadUpperGroupMap();
   }

   for ( int i = 0; i < VecSize; i++ )
   {
      HPartTimeInfo &Part = PartVec[i];
      TDateTime DateTime;
      StringToDateTime(Part.StartTime, DateTime);
      {
         vector<string> StrVec;
         SplitString(Part.PartName.c_str(), *h_g::JobNameDelimiter, StrVec, true);
         if ( StrVec.size() >= 2 && !SectionSet.empty() )
         {
            bool Found = false;
            for ( string GroupId = StrVec[0]; GroupId != ""; )
            {
               if ( SectionSet.find(GroupId) != SectionSet.end() )
               {
                  SectionSet.erase(GroupId);
                  Found = true;
               }
               map<UTF8String, UTF8String>::iterator Iter = MainForm->UpperGroupMap.find(GroupId.c_str());
               if ( Iter == MainForm->UpperGroupMap.end() )
               {
                  GroupId = "";
               }
               else
               {
                  GroupId = Iter->second.c_str();
               }
            }
            string JobName = StrVec[0] + ":" + StrVec[1];
            if ( SectionSet.find(JobName) != SectionSet.end() )
            {
               SectionSet.erase(JobName);
               Found = true;
            }
            if ( Found )
            {
               SplitterVec.push_back(DateTime);
            }
         }
      }
      int Start = SubDateTime(DateTime, BatchStartTime);
      StringToDateTime(Part.EndTime, DateTime);
      int End = SubDateTime(DateTime, BatchStartTime);
      for ( int j = Start; j < End && j < ParaVecSize; j++ )
      {
         ParaVec[j]++;
      }
   }

   TDateTime Time = BatchStartTime;

   for ( int i = 0; i < ParaVecSize; i++ )
   {
      HParaTimeInfo Info;
      Info.Time = Time;
      Info.Para = ParaVec[i];
      ParaTimeVec.push_back(Info);
      Time = Time + TDateTime(0, 0, 1, 0);
   }
}

void __fastcall TConcurrencyForm::DrawGrid()
{
   int Scale = 0;
   double KorM = 1;
   const char *KorMStr = "";
   char TmpStr[200 + 1];
   MaxValue = 0;

   for ( int i = 0; i < ParaTimeVec.size(); i++ )
   {
      HParaTimeInfo &Info = ParaTimeVec[i];
      if ( Info.Para > MaxValue )
      {
         MaxValue = Info.Para;
      }
   }

   Image1->Canvas->Font->Name = "Arial";
   Image1->Canvas->Font->Size = 8;
   Image1->Canvas->Font->Color = (TColor)RGB(242, 242, 242);
   Image1->Canvas->Brush->Style = bsClear;

   if ( MaxValue < 6 )
   {
      MaxValue = 6;
   }

   for ( int i = 0; i < 6; i++ )
   {
      int y = StartY + (int)(LengthY / 6.0 * i + 0.5);
      snprintf(TmpStr, 200, "%.*lf%s %s", Scale, ( MaxValue - MaxValue / 6 * i ) / KorM,
         KorMStr, "");
      Image1->Canvas->TextOut(LEFT + 90 - Image1->Canvas->TextWidth(TmpStr),
         TOP + y - 10, UTF8String(TmpStr));
   }

   snprintf(TmpStr, 200, "%.*lf%s %s", Scale, 0.0, KorMStr, "");
   Image1->Canvas->TextOut(LEFT + 90 - Image1->Canvas->TextWidth(TmpStr),
      TOP + EndY - 10, UTF8String(TmpStr));

   const HPeriodInfo &Period = PeriodArray[ComboBoxPeriod->ItemIndex];

   StringToDateTime(GetDateTime(UTF8String(EditEndTime->Text).c_str()), EndTime);

   if ( Period.TotalSec == 24 * 3600 )
   {
      StartTime = EndTime - TDateTime(1);
   }
   else
   {
      StartTime = EndTime - TDateTime(Period.TotalSec / 3600,
         Period.TotalSec % 3600 / 60, Period.TotalSec % 60, 0);
   }

   TotalSec = SubDateTime(EndTime, StartTime);
   Image1->Canvas->Font->Name = "Arial";
   Image1->Canvas->Font->Size = 8;
   Image1->Canvas->Brush->Style = bsClear;

   {
      Image1->Canvas->Font->Color = (TColor)RGB(214, 85, 85);
      UTF8String TimeStr = DateTimeToString2(EndTime);
      TextOutVert(LEFT + EndX - 6, TOP + EndY + Image1->Canvas->TextWidth(TimeStr) + 8, TimeStr);
      TimeStr = DateTimeToString2(StartTime);
      TextOutVert(LEFT + StartX - 6, TOP + EndY + Image1->Canvas->TextWidth(TimeStr) + 8, TimeStr);
   }

   {
      int Delta = Period.TotalSec / Period.BlockQty;
      TDateTime OneSec(0, 0, 1, 0);
      for ( TDateTime DateTime = EndTime - OneSec; DateTime > StartTime; DateTime -= OneSec )
      {
         unsigned short Hour;
         unsigned short Min;
         unsigned short Sec;
         unsigned short MSec;
         DateTime.DecodeTime(&Hour, &Min, &Sec, &MSec);
         if ( ( Min * 60 + Sec ) % Delta != 0 )
         {
            continue;
         }
         Image1->Canvas->Pen->Mode = pmCopy;
         Image1->Canvas->Pen->Style = psDot;
         int x = EndX - (int)((double)LengthX / TotalSec * SubDateTime(EndTime, DateTime) + 0.5);
         if ( EndX - x < 10 || x - StartX < 10 )
         {
            continue;
         }
         bool MarkedFlag = false;
         UTF8String TimeStr;
         if ( Hour == 0 && Min == 0 && Sec == 0 )
         {
            MarkedFlag = true;
            TimeStr = DateTimeToString2(DateTime);
         }
         else
         {
            if ( Period.HourFlag )
            {
               if ( Min == 0 && Sec == 0 )
               {
                  MarkedFlag = true;
               }
               TimeStr = DateTimeToString1(DateTime);
            }
            else
            {
               if ( Sec == 0 )
               {
                  MarkedFlag = true;
               }
               TimeStr = DateTimeToString3(DateTime);
            }
         }
         if ( MarkedFlag )
         {
            Image1->Canvas->Pen->Color = (TColor)RGB(89, 89, 89);
            Image1->Canvas->Font->Color = (TColor)RGB(214, 85, 85);
         }
         else
         {
            Image1->Canvas->Pen->Color = (TColor)RGB(69, 69, 69);
            Image1->Canvas->Font->Color = (TColor)RGB(242, 242, 242);
         }
         Image1->Canvas->MoveTo(LEFT + x, TOP + StartY);
         Image1->Canvas->LineTo(LEFT + x, TOP + EndY);
         TextOutVert(LEFT + x - 6, TOP + EndY + Image1->Canvas->TextWidth(TimeStr) + 8, TimeStr);
      }
   }
}

void __fastcall TConcurrencyForm::DrawSplitter()
{
   Image1->Canvas->Pen->Style = psSolid;
   Image1->Canvas->Pen->Color = clWhite;

   for ( int i = 0; i < SplitterVec.size(); i++ )
   {
      TDateTime &DateTime = SplitterVec[i];
      if ( DateTime <= StartTime || DateTime > EndTime )
      {
         continue;
      }
      int x = EndX - (int)((double)LengthX / TotalSec * SubDateTime(EndTime, DateTime) + 0.5);
      Image1->Canvas->MoveTo(LEFT + x, TOP + StartY);
      Image1->Canvas->LineTo(LEFT + x, TOP + EndY);
   }
}

//---------------------------------------------------------------------------

void __fastcall TConcurrencyForm::ButtonDrawChartClick(TObject *Sender)
{
   if ( !StringToDateTime(GetDateTime(UTF8String(EditEndTime->Text).c_str()), EndTime) )
   {
      h_g::ShowMessage(UTF8String(h_g::I18nString("t_concurrencyform:INCORRECT_END_TIME_FORMAT")));
      return;
   }

   PrepareData();
   DrawBackground();
   DrawGrid();
   DrawLines();
   DrawSplitter();
}
//---------------------------------------------------------------------------
void __fastcall TConcurrencyForm::TextOutVert(int x, int y, const UTF8String &Str)
{
   int StrWidth = Image1->Canvas->TextWidth(Str);
   int StrHeight = Image1->Canvas->TextHeight(Str);
   TRect Rect(100, 600, 100 + StrWidth, 600 + StrHeight);

   Image1->Canvas->TextOut(100, 600, Str);

   for ( int i = 0; i < StrWidth; i++ )
   {
      for ( int j = 0; j < StrHeight; j++ )
      {
         Image1->Canvas->Pixels[x + j][y - i] = Image1->Canvas->Pixels[100 + i][600 + j];
      }
   }

   Image1->Canvas->Brush->Color = (TColor)RGB(43, 43, 43);
   Image1->Canvas->FillRect(Rect);
}
void __fastcall TConcurrencyForm::DrawLines()
{
#ifdef SIMBAT_ENTERPRISE
   DrawLines_aux(StartX, EndX, LengthX, StartY, EndY, LengthY);
#endif
}

void __fastcall TConcurrencyForm::ButtonSaveChartClick(TObject *Sender)
{
   SaveDialog1->DefaultExt = "bmp";
   SaveDialog1->FileName = "";
   SaveDialog1->Filter =
      "Bit map file (*.bmp)|*.bmp";
   SaveDialog1->FilterIndex = 1;
   SaveDialog1->InitialDir = ".";
   SaveDialog1->Options = TOpenOptions() << ofOverwritePrompt
      << ofPathMustExist << ofEnableSizing;
   SaveDialog1->Title = UTF8String(h_g::I18nString("t_concurrencyform:SAVE_CHART_AS"));

   if( !SaveDialog1->Execute() )
      return;

   TRect Rect(0, 0, Image1->Width, Image1->Height);
   TPicture *Pic = new TPicture();

   Pic->Bitmap->Width = Image1->Width;
   Pic->Bitmap->Height = Image1->Height;
   Pic->Bitmap->Canvas->CopyRect(Rect, Image1->Canvas, Rect);
   Pic->SaveToFile(SaveDialog1->FileName);
   delete(Pic);
}
//---------------------------------------------------------------------------

void __fastcall TConcurrencyForm::ButtonWindowClick(TObject *Sender)
{
   switch ( WindowHeightIdx )
   {
   case 0 :
      Width = Screen->Width;
      Height = Screen->Height / 2;
      break;
   case 1 :
      Width = Screen->Width;
      Height = Screen->Height / 3;
      break;
   case 2 :
      Width = Screen->Width;
      Height = Screen->Height / 4;
      break;
   case 3 :
      Width = Screen->Width;
      Height = Screen->Height;
      break;
   }

   WindowHeightIdx = ( WindowHeightIdx + 1 ) % 4;
}
//---------------------------------------------------------------------------



void __fastcall TConcurrencyForm::ButtonPanelClick(TObject *Sender)
{
   ShowPanelFlag = !ShowPanelFlag;
   Panel1->Visible = ShowPanelFlag;
}
//---------------------------------------------------------------------------

void __fastcall TConcurrencyForm::FormKeyUp(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
   if ( Key == VK_F3 )
   {
      ButtonWindowClick(NULL);
   }

   if ( Key == VK_F2 )
   {
      ButtonPanelClick(NULL);
   }
}
//---------------------------------------------------------------------------

